package com.papper.mng.filter;

import com.papper.common.bean.sys.SysLimit;
import com.papper.common.bean.sys.SysResource;
import com.papper.common.bean.sys.SysSystem;
import com.papper.common.bean.sys.SysUser;
import com.papper.common.config.PapperStorage;
import com.papper.common.constant.SystemConstants;
import com.papper.common.service.sys.SysLimitService;
import com.papper.common.service.sys.SysPageConfigService;
import com.papper.common.service.sys.SysResourceService;
import com.papper.common.utils.PapperSpringUtil;
import com.papper.common.utils.tool.StringTool;
import com.papper.mng.controller.WebContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import tk.mybatis.mapper.util.StringUtil;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;

/**
 * @Author:Lajiao
 * @Date:2014年8月22日
 * @Time:上午9:19:57
 * @Description:请求过滤条件
 */
public class RequestFilter implements Filter {
    private final static Logger                         logger     = LoggerFactory.getLogger(RequestFilter.class);
    private final static String                         LOGIN_PATH = "/login";
    private final static String                         LIMIT_PATH = "/limit";

    @Override
    public void init(FilterConfig config) throws ServletException {
        FilterConfigTool.I().initPropertys();
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest  request  = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        HttpSession         session  = request.getSession();
        String              strUrl   = request.getServletPath();
        /**
         * 通用数据设置
         */
        WebContext.setServletRequest(request);
        WebContext.setServletResponse(response);
        WebContext.setHttpSession(request.getSession());
        /**
         * 通用CDN缓存
         */
        String systemCdnPath = PapperStorage.SystemConfig("systemCdnPath");
        if (StringUtil.isEmpty(systemCdnPath)) {
            request.setAttribute("systemCdnPath", "");
        } else {
            request.setAttribute("systemCdnPath", systemCdnPath);
        }
        /**
         * 过滤外请求
         */
        if (FilterConfigTool.I().isExclude(strUrl)) {
            chain.doFilter(servletRequest, servletResponse);
            return;
        }
        /**
         * 用户未登录
         */
        SysUser sysUser = (SysUser) session.getAttribute(SystemConstants.SESSION.SESSION_ADMIN_LOGIN);
        if (sysUser == null) {
            toLogin(request, response, strUrl, null);
            return;
        }
        // 单点登录限制
        String cacheValue = LoginLimitCache.I().getSession(sysUser.getId().toString());
        if (cacheValue != null && !cacheValue.equals(session.getId())) {
            toLogin(request, response, strUrl, "您在其它地方已登录,请确认是否本人登录");
            return;
        } else if (cacheValue == null) {
            LoginLimitCache.I().putSession(sysUser.getId().toString(), session.getId());
        }
        /**
         * 用户已登录-限制外请求
         */
        if (FilterConfigTool.I().isSource(strUrl)) {
            chain.doFilter(servletRequest, servletResponse);
            return;
        }
        /**
         * 用户已登录-限制内请求
         */
        SysResource sysResource = match(strUrl);
        if (sysResource == null) {
            if (sysUser != null && sysUser.getId().intValue() == 0) {
                chain.doFilter(servletRequest, servletResponse);
            } else {
                toLimit(request, response);
            }
            return;
        }
        if (sysUser != null && sysUser.getId().intValue() == 0) {
            // 超级用户
            request.setAttribute("showFields", showFields(sysResource, sysUser));
            chain.doFilter(servletRequest, servletResponse);
            return;
        } else {
            SysLimitService sysLimitService = (SysLimitService) PapperSpringUtil.getBean("sysLimitService");
            SysLimit        sysLimit        = sysLimitService.getUserLimit(sysUser.getLimitType(), sysUser.getId(), sysUser.getGroupId(), sysResource.getId());
            if (sysLimit == null) {
                toLimit(request, response);
                return;
            }
        }
        // 用户放行
        request.setAttribute("showFields", showFields(sysResource, sysUser));
        chain.doFilter(servletRequest, servletResponse);
        return;
    }

    @Override
    public void destroy() {
        return;
    }

    public void toLimit(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String strContextPath = request.getContextPath();
        String strRedirect    = "/" + strContextPath + "/" + LIMIT_PATH;
        strRedirect = strRedirect.replaceAll("[/]+", "/");
        response.sendRedirect(strRedirect);
        return;
    }

    public void toLogin(HttpServletRequest request, HttpServletResponse response, String callBack, String msg) throws IOException {
        WebContext.getHttpSession().removeAttribute(SystemConstants.SESSION.SESSION_ADMIN_LOGIN);
        String       strContextPath = request.getContextPath();
        StringBuffer strRedirect    = new StringBuffer();
        strRedirect.append("/").append(strContextPath);
        strRedirect.append("/").append(LOGIN_PATH);
        strRedirect.append("?callBack=").append(URLEncoder.encode(callBack, "UTF-8"));
        if (!StringTool.isEmpty(msg)) {
            strRedirect.append("&error=").append(URLEncoder.encode(msg, "UTF-8"));
        }
        response.sendRedirect(strRedirect.toString().replaceAll("[/]+", "/"));
        return;
    }

    /**
     * 路径匹配
     *
     * @param url the url
     * @return the sys limit
     */
    public SysResource match(String url) {
        if (url == null || StringUtil.isEmpty(url)) {
            return null;
        }
        SysSystem          sysSystem   = PapperStorage.System();
        SysResourceService s           = (SysResourceService) PapperSpringUtil.getBean("sysResourceService");
        List<SysResource>  allResource = s.findAll();
        if (allResource == null || allResource.isEmpty()) {
            return null;
        }
        String compareUrl;
        for (SysResource sr : allResource) {
            compareUrl = "/" + sr.getResUrl();
            if (url.equals(compareUrl) && sr.getSystemId().intValue() == sysSystem.getId().intValue()) {
                return sr;
            }
        }
        return null;
    }

    /**
     * 模块显示配置.
     *
     * @param sysResource the sys resource
     * @param sysUser     the sys user
     * @return the string
     */
    public String showFields(SysResource sysResource, SysUser sysUser) {
        if (sysResource == null) {
            return null;
        }
        SysSystem sysSystem = PapperStorage.System();
        if (sysSystem == null) {
            return null;
        }
        SysPageConfigService sysPageConfigService = (SysPageConfigService) PapperSpringUtil.getBean("sysPageConfigService");
        if (sysPageConfigService == null) {
            return null;
        }
        String showFields = sysPageConfigService.findShowItem(sysSystem.getSystemCode(), StringTool.nullToEmpty(sysUser.getId()), sysResource.getResLimit());
        return showFields;
    }
}
